package com.ctshk.rpc.iotc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.air.service.IAirProductService;
import com.ctshk.rpc.airexpress.service.IAirportExpressService;
import com.ctshk.rpc.bus.service.IBusProductService;
import com.ctshk.rpc.custom.service.ICustomizedTripScheduleService;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.finance.service.IFinanceOnAccountCurrencyQuotaService;
import com.ctshk.rpc.iotc.dto.OperatePromotionListDTO;
import com.ctshk.rpc.iotc.dto.OperatePromotionQueryDTO;
import com.ctshk.rpc.iotc.entity.OperatePromotion;
import com.ctshk.rpc.iotc.entity.OperatePromotionProduct;
import com.ctshk.rpc.iotc.mapper.OperatePromotionMapper;
import com.ctshk.rpc.iotc.mapper.OperatePromotionProductMapper;
import com.ctshk.rpc.iotc.req.*;
import com.ctshk.rpc.iotc.service.IOperatePromotionService;
import com.ctshk.rpc.localfun.req.LocalFunResourceReq;
import com.ctshk.rpc.localfun.service.ILocalFunResourceService;
import com.ctshk.rpc.scenic.req.ScenicProductListReq;
import com.ctshk.rpc.scenic.service.IScenicProductService;
import com.ctshk.rpc.season.service.ISeasonFixedProductService;
import com.ctshk.rpc.ship.req.ShipProductPageReq;
import com.ctshk.rpc.ship.service.IShipProductService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.tour.dto.schedule.TripScheduleItocDTO;
import com.ctshk.rpc.tour.service.ISeriesTripScheduleService;
import com.ctshk.rpc.train.service.ITrainProductService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 推广码 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-01-22
 */
@DubboService
public class OperatePromotionServiceImpl extends ServiceImpl<OperatePromotionMapper, OperatePromotion> implements IOperatePromotionService {

    @Autowired
    private OperatePromotionMapper operatePromotionMapper;
    @Autowired
    private OperatePromotionProductMapper operatePromotionProductMapper;
    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private ISeriesTripScheduleService iSeriesTripScheduleService;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private IAirProductService airProductService;
    @DubboReference
    private IAirportExpressService airportExpressService;
    @DubboReference
    private IScenicProductService scenicProductService;
    @DubboReference
    private IBusProductService busProductService;
    @DubboReference
    private ITrainProductService trainProductService;
    @DubboReference
    private ICustomizedTripScheduleService customizedTripScheduleService;
    @DubboReference
    private IShipProductService shipProductService;
    @DubboReference
    private ILocalFunResourceService localFunResourceService;
    @DubboReference
    private ISeasonFixedProductService seasonFixedProductService;
    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISysPermissionService sysPermissionService;
    @DubboReference
    private IFinanceOnAccountCurrencyQuotaService foacqs;
    @DubboReference
    private IFinanceBillService financeBillService;

    /**
     * 新增推广码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(OperatePromotionAddReq req, TokenUser tokenUser) {
        OperatePromotion operatePromotion = EntityUtil.copy(req, OperatePromotion.class);
        //校验活动ID
        QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OperatePromotion::getActivityCode, operatePromotion.getActivityCode());
        queryWrapper.lambda().eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode());
        if (0 != operatePromotionMapper.selectCount(queryWrapper)) {
            return Result.failed(SystemError.IOTC_40001);
        }
        if(req.getRelationIdList() == null || req.getRelationIdList().size() < 1){
            return Result.failed(SystemError.IOTC_400025);
        }
        long id = IdWorker.getId();
        LocalDateTime now = LocalDateTime.now();
        operatePromotion.setId(id);
        if (req.getSaveStatus() == 1) {
            operatePromotion.setStatus(OperatePromotionStatus.STATUS_1.getCode());//新增默认未提交
        } else {
            operatePromotion.setStatus(OperatePromotionStatus.STATUS_2.getCode());//新增默认审批中
        }
        operatePromotion.setGmtCreate(now);
        operatePromotion.setGmtModified(now);
        operatePromotion.setIsDeleted(IsDeletedCode.NO.getCode());
        operatePromotion.setStockAmount(req.getTotalAmount());
        operatePromotion.setStockNum(req.getTotalDiscountQuota());
        operatePromotion.setModifiedId(tokenUser.getId());
        operatePromotion.setCreateId(tokenUser.getId());
        operatePromotion.setGmtModified(now);
        operatePromotion.setGmtCreate(now);
        //新增推广码
        int insert = baseMapper.insert(operatePromotion);
        if (insert > 0 && null != req.getRelationIdList()) {
            OperatePromotionProduct operatePromotionProduct = new OperatePromotionProduct();
            operatePromotionProduct.setCodeId(id);
            operatePromotionProduct.setIsDeleted(IsDeletedCode.NO.getCode());
            operatePromotionProduct.setGmtCreate(now);
            operatePromotionProduct.setGmtModified(now);
            operatePromotionProduct.setCreateId(tokenUser.getId());
            for (Long relationId : req.getRelationIdList()) {
                operatePromotionProduct.setId(IdWorker.getId());
                operatePromotionProduct.setRelationId(relationId);
                //新增推广码适用产品
                operatePromotionProductMapper.insert(operatePromotionProduct);
            }
        }
        if (insert > 0 && req.getSaveStatus() == 2) { //审批
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.IOTC.getCode(),
                    SysApprovalType.PROMOTION_OPRATION.getCode(), id,
                    tokenUser.getId(), null, null);
            if (!approvalResult.isSuccess()) {
                log.error(approvalResult.getMsg());
                return approvalResult;
            }
        }
        return Result.success(id);
    }

    /**
     * 编辑推广码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(OperatePromotionUpdateReq req, TokenUser tokenUser) {
        if(req.getRelationIdList() == null || req.getRelationIdList().size() < 1){
            return Result.failed(SystemError.IOTC_400025);
        }
        OperatePromotion operatePromotion = EntityUtil.copy(req, OperatePromotion.class);
        LocalDateTime now = LocalDateTime.now();
        operatePromotion.setGmtModified(now);
        operatePromotion.setModifiedId(tokenUser.getId());
        //如果要修改 那么这张单就改成未提交状态
        if (req.getSaveStatus() == 2) {
            operatePromotion.setStatus(OperatePromotionStatus.STATUS_2.getCode());
        } else {
            operatePromotion.setStatus(OperatePromotionStatus.STATUS_1.getCode());
        }
        //更新推广码
        int i = baseMapper.updateById(operatePromotion);
        //查询推广码对应的产品
        if (i > 0 && CollectionUtils.isNotEmpty(req.getRelationIdList())) {
            QueryWrapper<OperatePromotionProduct> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(OperatePromotionProduct::getCodeId, req.getId());
            List<OperatePromotionProduct> promotionProductList = operatePromotionProductMapper.selectList(queryWrapper);
            List<Long> relationIdList = new ArrayList<>();
            for (OperatePromotionProduct item : promotionProductList) {
                relationIdList.add(item.getRelationId());
            }
            //比对推广码新增对应产品
            OperatePromotionProduct product = new OperatePromotionProduct();
            OperatePromotionProduct newProduct = new OperatePromotionProduct();
            newProduct.setCreateId(tokenUser.getId());
            newProduct.setModifiedId(tokenUser.getId());
            newProduct.setGmtCreate(now);
            newProduct.setGmtModified(now);
            newProduct.setIsDeleted(IsDeletedCode.NO.getCode());
            for (Long newRelationId : req.getRelationIdList()) {
                //新的产品不再原来的表中就添加
                if (!relationIdList.contains(newRelationId)) {
                    newProduct.setId(IdWorker.getId());
                    newProduct.setRelationId(newRelationId);
                    newProduct.setCodeId(req.getId());
                    operatePromotionProductMapper.insert(newProduct);
                }
            }
            //比对推广码减少对应产品
            List<Long> newRelationIdList = req.getRelationIdList();
            for (Long relationId : relationIdList) {
                //新添加的产品里面筛选老的产品看看有没有被删除的
                if (!newRelationIdList.contains(relationId)) {
                    operatePromotionProductMapper.updateByCodeIdAndRelationId(req.getId(), relationId);
                }
            }
        }
        if (i > 0 && req.getSaveStatus() == 2) { //审批
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.IOTC.getCode(),
                    SysApprovalType.PROMOTION_OPRATION.getCode(), operatePromotion.getId(),
                    tokenUser.getId(), null, null);
            if (!approvalResult.isSuccess()) {
                log.error(approvalResult.getMsg());
                return approvalResult;
            }
        }
        return Result.success(req.getId());
    }

    @Override
    public Result updateStatus(CodeStatusReq req, TokenUser tokenUser) {
        OperatePromotion op = new OperatePromotion();
        op.setId(req.getId());
        op.setStatus(req.getStatus());
        int i = baseMapper.updateById(op);
        if (i > 0) {
            return Result.success();
        }
        return Result.failed(SystemError.CMS_23002);
    }

    @Override
    public Result approvalCode(Long codeId, TokenUser tokenUser) {
        OperatePromotion operatePromotion = baseMapper.selectById(codeId);
        if (operatePromotion != null) { //审批
            if (operatePromotion.getStatus() == OperatePromotionStatus.STATUS_1.getCode()) {
                operatePromotion.setStatus(OperatePromotionStatus.STATUS_2.getCode());
                int i = baseMapper.updateById(operatePromotion);
                if (i > 0) {
                    Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.IOTC.getCode(),
                            SysApprovalType.PROMOTION_OPRATION.getCode(), operatePromotion.getId(),
                            tokenUser.getId(), null, null);
                    if (!approvalResult.isSuccess()) {
                        log.error(approvalResult.getMsg());
                        return approvalResult;
                    } else {
                        return Result.success();
                    }
                }
            }
        }
        return Result.failed(SystemError.SYS_437);
    }

    /**
     * 查询推广码详情
     * 下方链接快速查看适用产品的业务类型
     *
     * @see com.ctshk.common.enums.SystemBusinessType
     */
    @Override
    public Result<OperatePromotionQueryDTO> query(OperatePromotionQueryReq req) {
        QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", req.getId());
        queryWrapper.eq("is_deleted", IsDeletedCode.NO.getCode());
        OperatePromotion operatePromotion = operatePromotionMapper.selectOne(queryWrapper);
        if (null == operatePromotion) {
            throw new BusinessException(SystemError.IOTC_40002);
        }
        OperatePromotionQueryDTO operatePromotionQueryDTO = EntityUtil.copy(operatePromotion, OperatePromotionQueryDTO.class);
        //接口对接
        QueryWrapper<OperatePromotionProduct> op = new QueryWrapper<>();
        op.eq("code_id", req.getId());
        op.eq("is_deleted", IsDeletedCode.NO.getCode());
        //不要分页，在前端使用静态分页方便前端编辑的时候获取数据
//        IPage<OperatePromotionProduct> page = new Page<>(req.getPageNo(), req.getPageSize());
//        IPage<OperatePromotionProduct> iPage = operatePromotionProductMapper.selectPage(page, op);
        //一次性查出所有产品
        List<OperatePromotionProduct> operatePromotionProducts = operatePromotionProductMapper.selectList(op);
        if (CollectionUtils.isNotEmpty(operatePromotionProducts)) {
            List<Long> list = operatePromotionProducts.stream().map(e -> e.getRelationId()).collect(Collectors.toList());
            operatePromotionQueryDTO.setIdList(list);
            switch (operatePromotionQueryDTO.getBusinessType()) {
                case 1: //出境遊
                    List<TripScheduleItocDTO> tripScheduleItocDTOS1 = iSeriesTripScheduleService.queryScheduleListByIdList(list, 1);
                    setAirTicketPage(tripScheduleItocDTOS1, operatePromotionQueryDTO);
                    break;
                case 2://入境遊
                    List<TripScheduleItocDTO> tripScheduleItocDTOS2 = iSeriesTripScheduleService.queryScheduleListByIdList(list, 2);
                    setAirTicketPage(tripScheduleItocDTOS2, operatePromotionQueryDTO);
                    break;
                case 3://出境定制
                case 4://入境定制
                case 5://會議會獎
                    //3-4-5是同一个接口  出境类型(1 出境定制 2 入境定制 3 会议会奖)
                    setAirTicketPage(customizedTripScheduleService.queryByIds(list, operatePromotionQueryDTO.getBusinessType()), operatePromotionQueryDTO);
                    break;
                case 6://固定套票
                    String join = org.apache.commons.lang.StringUtils.join(list.toArray(), ",");
                    setAirTicketPage(seasonFixedProductService.getSeasonProductList(join), operatePromotionQueryDTO);
                    break;
                case 7://動態套票
                    break;
                case 8://酒店
                    break;
                case 9://機票
                    setAirTicketPage(airProductService.operationsCenterGetProductByIds(list).getData(), operatePromotionQueryDTO);
                    break;
                case 10://火車票
                    setAirTicketPage(trainProductService.queryProductListByIdForIotc(list).getData(), operatePromotionQueryDTO);
                    break;
                case 11://船票
                    ShipProductPageReq sppr = new ShipProductPageReq();
                    sppr.setProductIds(list);
                    setAirTicketPage(shipProductService.queryShipList2(sppr), operatePromotionQueryDTO);
                    break;
                case 12://巴士票
                    setAirTicketPage(busProductService.queryProductListByIdForIotc(list).getData(), operatePromotionQueryDTO);
                    break;
                case 13://機場快線
                    setAirTicketPage(airportExpressService.getListByIds(list), operatePromotionQueryDTO);
                    break;
                case 14://景點門票
                    ScenicProductListReq splr = new ScenicProductListReq();
                    splr.setIds(list);
                    setAirTicketPage(scenicProductService.getListByIds(splr).getData(), operatePromotionQueryDTO);
                    break;
                case 15://當地玩樂
                    LocalFunResourceReq lfrr = new LocalFunResourceReq();
                    lfrr.setProductIds(list);
                    setAirTicketPage(localFunResourceService.queryListByProductIds2(lfrr), operatePromotionQueryDTO);
                    break;
                case 16://簽證
                    break;
                case 17://證件辦理
                    break;
                case 18://商品
                    break;
                case 19://财务中心
                    break;
                case 20://運營中心
                    break;
                case 21://供應商預訂
                    break;
                case 22://系統資源
                    break;
                case 23://套票
                    break;
                case 24://保险
                    break;
            }
        } else {
            operatePromotionQueryDTO.setIdList(null);
        }
        return Result.success(operatePromotionQueryDTO);
    }

    private <T> void setAirTicketPage(List<T> list, OperatePromotionQueryDTO operatePromotionQueryDTO) {
        if (!list.isEmpty()) {
            operatePromotionQueryDTO.setAirTicketPage((List<Object>) list);
        }
    }

//    @Override
//    public PageResponse<TripScheduleListDTO> getTrip(OperatePromotionQueryListReq req) {
//        Page<OperatePromotionProduct> page = new Page<>(req.getPageNo(),req.getPageSize());
//        QueryWrapper<OperatePromotionProduct> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().eq(OperatePromotionProduct::getRelationId, req.getId());
//        Page<OperatePromotionProduct> iPage = operatePromotionProductMapper.selectPage(page, queryWrapper);
//        TripScheduleListIdReq tripScheduleListIdReq = new TripScheduleListIdReq();
//        tripScheduleListIdReq.setListId(req.getListId());
//        List<TripScheduleListDTO> tripScheduleList = iSeriesTripScheduleService.getTripScheduleList(tripScheduleListIdReq);
//        PageResponse<TripScheduleListDTO> result = new PageResponse<>(tripScheduleList,page.getCurrent() == 1,
//                page.getTotal() <= (page.getCurrent() * page.getSize()),
//                page.getTotal(), page.getCurrent(), page.getSize());
//
//        return result;
//    }

    /**
     * 查询推广码列表
     *
     * @param req
     * @return
     */
    @Override
    public PageResponse<OperatePromotionListDTO> list(OperatePromotionListReq req, TokenUser tokenUser) {
        IPage<OperatePromotion> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
        //判断是否有权限查看
        if (!GlobalConstants.Role.isAdmin(tokenUser.getUsername())) {
            if (req.getMenuId() == null) {
                throw new BusinessException(SystemError.SYSTEM_2106);
            }
            Result<List<Long>> permissionResult = sysPermissionService.queryPermission(req.getMenuId(), tokenUser.getId());
            if (!permissionResult.isSuccess()) {
                SystemError result = SystemError.getDefined(permissionResult.getCode());
                throw new BusinessException(result);
            }
            queryWrapper.lambda().in(OperatePromotion::getCreateId, permissionResult.getData());
        }
        queryWrapper.lambda().ge(null != req.getActivityBegin1(), OperatePromotion::getActivityBegin, req.getActivityBegin1())
                .le(null != req.getActivityBegin2(), OperatePromotion::getActivityBegin, req.getActivityBegin2())
                .ge(null != req.getActivityEnd1(), OperatePromotion::getActivityEnd, req.getActivityEnd1())
                .le(null != req.getActivityEnd2(), OperatePromotion::getActivityEnd, req.getActivityEnd2())
                .ge(null != req.getGmtCreate1(), OperatePromotion::getGmtCreate, req.getGmtCreate1())
                .le(null != req.getGmtCreate2(), OperatePromotion::getGmtCreate, req.getGmtCreate2())
                .eq(null != req.getStatus(), OperatePromotion::getStatus, req.getStatus())
                .eq(null != req.getCreateId(), OperatePromotion::getCreateId, req.getCreateId())
                .like(StringUtils.isNotBlank(req.getActivityCode()), OperatePromotion::getActivityCode, req.getActivityCode())
                .like(StringUtils.isNotBlank(req.getName()), OperatePromotion::getName, req.getName())
                .eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode())
                .orderByDesc(OperatePromotion::getGmtModified);
        //需定义排序规则:按修改时间倒序
        IPage<OperatePromotion> iPage = baseMapper.selectPage(page, queryWrapper);
        List<OperatePromotion> operatePromotionList = iPage.getRecords();
        if (CollectionUtils.isEmpty(operatePromotionList)) {
            return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        List<OperatePromotionListDTO> opl = EntityUtil.copyList(operatePromotionList, OperatePromotionListDTO.class);
        //填充创建人名称  修改人名称
        Set<Long> ids = opl.stream().map(e -> e.getCreateId()).collect(Collectors.toSet());
        Set<Long> uids = opl.stream().map(e -> e.getModifiedId()).collect(Collectors.toSet());
        ids.addAll(uids);
        List<UserDTO> users = sysUserService.getUsers(ids);
        Map<Long, String> us = new HashMap<>();
        users.stream().forEach(e -> us.put(e.getId(), e.getFullName()));
        opl.stream().forEach(e -> {
            e.setCreateName(us.get(e.getCreateId()));
            e.setModifiedName(us.get(e.getModifiedId()));
        });
        return new PageResponse<>(opl, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public Result<OperatePromotionQueryDTO> queryConform(OperatePromotionConformReq req) {
        try {
            QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(OperatePromotion::getActivityCode, req.getActivityCode())
                    .eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(OperatePromotion::getBusinessType, req.getBusinessType());
            OperatePromotion operatePromotion = baseMapper.selectOne(queryWrapper);
            if (operatePromotion == null) {
                return Result.failed(SystemError.IOTC_40002);
            }
            //判断状态是否有效
            if (operatePromotion.getStatus() != OperatePromotionStatus.STATUS_4.getCode()) {
                return Result.failed(SystemError.IOTC_400010);
            }
            //获取当前时间和星期数
            LocalDateTime now = LocalDateTime.now();
            String week = String.valueOf(now.getDayOfWeek().getValue());
            //是否符合活动有效期
            if (!(now.isAfter(operatePromotion.getActivityBegin()) && now.isBefore(operatePromotion.getActivityEnd()))) {
                OperatePromotion promotion = new OperatePromotion();
                promotion.setStatus(OperatePromotionStatus.STATUS_6.getCode());
                promotion.setId(operatePromotion.getId());
                baseMapper.updateById(promotion);
                return Result.failed(SystemError.IOTC_400011);
            }
            // 是否符合活动周期
            if (operatePromotion.getActivityCycle() == OperatePromotionActivityCycle.ACTIVITY_CYCLE_2.getCode()) {
                String[] strings = operatePromotion.getActivityCycleWeeks().split(",");
                List<String> list = Arrays.asList(strings);
                if (!list.contains(week)) {
                    return Result.failed(SystemError.IOTC_400012);
                }
            }
            //判断剩余笔数
            if (operatePromotion.getStockNum() == 0) {
                return Result.failed(SystemError.IOTC_400013);
            }
            //是否符合满减
            int i = req.getTotalPaidIn().compareTo(operatePromotion.getFullAmount());
            if (i < 0) {
                return Result.failed(SystemError.IOTC_400014);
            }
            //判断剩余金额是否足够
            int compare = operatePromotion.getStockAmount().compareTo(operatePromotion.getReductionAmount());
            if (compare < 0) {
                return Result.failed(SystemError.IOTC_400015);
            }
            //判断是否属于适用产品
            QueryWrapper<OperatePromotionProduct> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(OperatePromotionProduct::getCodeId, operatePromotion.getId())
                    .eq(OperatePromotionProduct::getRelationId, req.getRelationId())
                    .eq(OperatePromotionProduct::getIsDeleted, IsDeletedCode.NO.getCode());
            if (operatePromotionProductMapper.selectCount(wrapper) != 1) {
                return Result.failed(SystemError.IOTC_400016);
            }
            //判断是否符合优惠对象
            if (!getDiscountObjectsJsonBool(operatePromotion.getDiscountObjectsJson(), req.getDiscountObjectId())) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断是否符合渠道范围
            if (!getDiscountObjectsJsonBool(operatePromotion.getChannelsJson(), req.getChannelId())) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断是否符合适用部门
            if (!getDepartmentsJsonBool(operatePromotion.getDepartmentsJson(), req.getUserId())) {
                return Result.failed(SystemError.IOTC_40004);
            }
            OperatePromotionQueryDTO operatePromotionQueryDTO = EntityUtil.copy(operatePromotion, OperatePromotionQueryDTO.class);
            return Result.success(operatePromotionQueryDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.failed(SystemError.IOTC_40004);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deduct(OperatePromotionDeductReq req, TokenUser tokenUser) {
        try {
            QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(OperatePromotion::getId, req.getId())
                    .eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(OperatePromotion::getBusinessType, req.getBusinessType());
            OperatePromotion operatePromotion = baseMapper.selectOne(queryWrapper);
            if (operatePromotion == null) {
                return Result.failed(SystemError.IOTC_40002);
            }
            //判断状态是否有效
            if (operatePromotion.getStatus() != OperatePromotionStatus.STATUS_4.getCode()) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //获取当前时间和星期数
            LocalDateTime now = LocalDateTime.now();
            String week = String.valueOf(now.getDayOfWeek().getValue());
            //是否符合活动有效期
            if (!(now.isAfter(operatePromotion.getActivityBegin()) && now.isBefore(operatePromotion.getActivityEnd()))) {
                OperatePromotion promotion = new OperatePromotion();
                promotion.setStatus(OperatePromotionStatus.STATUS_6.getCode());
                promotion.setId(operatePromotion.getId());
                baseMapper.updateById(promotion);
                return Result.failed(SystemError.IOTC_40004);
            }
            //是否符合活动周期
            if (operatePromotion.getActivityCycle() == OperatePromotionActivityCycle.ACTIVITY_CYCLE_2.getCode()) {
                String[] strings = operatePromotion.getActivityCycleWeeks().split(",");
                List<String> list = Arrays.asList(strings);
                if (!list.contains(week)) {
                    return Result.failed(SystemError.IOTC_40004);
                }
            }
            //判断剩余笔数  (如果没有设置笔数那么就是空的话就不验证了)
            if (operatePromotion.getStockNum() != null && operatePromotion.getStockNum() == 0) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //是否符合满减
            int i = req.getTotalPaidIn().compareTo(operatePromotion.getFullAmount());
            if (i < 0) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断剩余金额是否足够
            int compare = operatePromotion.getStockAmount().compareTo(operatePromotion.getReductionAmount());
            if (compare < 0) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断是否属于适用产品
            QueryWrapper<OperatePromotionProduct> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(OperatePromotionProduct::getCodeId, operatePromotion.getId())
                    .eq(OperatePromotionProduct::getRelationId, req.getRelationId())
                    .eq(OperatePromotionProduct::getIsDeleted, IsDeletedCode.NO.getCode());
            if (operatePromotionProductMapper.selectCount(wrapper) == 0) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断是否符合优惠对象
            if (!getDiscountObjectsJsonBool(operatePromotion.getDiscountObjectsJson(), req.getDiscountObjectId())) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断是否符合渠道范围
            if (!getDiscountObjectsJsonBool(operatePromotion.getChannelsJson(), req.getChannelId())) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //判断是否符合适用部门
            if (!getDepartmentsJsonBool(operatePromotion.getDepartmentsJson(), tokenUser.getId())) {
                return Result.failed(SystemError.IOTC_40004);
            }
            //扣减剩余金额
            BigDecimal stockAmount = operatePromotion.getStockAmount().subtract(operatePromotion.getReductionAmount());
            //写入扣减名额和金额
            OperatePromotion promotion = new OperatePromotion();
            promotion.setId(req.getId());
            if (operatePromotion.getStockNum() != null) {
                //不是无限制就扣减名额
                promotion.setStockNum(operatePromotion.getStockNum() - 1);
            }
            promotion.setStockAmount(stockAmount);
            promotion.setGmtModified(now);
            promotion.setModifiedId(tokenUser.getId());
            int update = baseMapper.updateById(promotion);
            if (update > 0) {
                return Result.success();
            }
            //新增一笔内部挂账记录
//            BillAddCollectionReq bacr = EntityUtil.copy(req, BillAddCollectionReq.class);
//            bacr.setCollectionAmount(operatePromotion.getReductionAmount());//实际优惠金额
//            bacr.setCollectionTime(LocalDateTime.now());//消费时间当前
//            List<Long> list = new ArrayList<>();
//            list.add(req.getRelationId());
//            bacr.setProductId(list);//产品ID
//            bacr.setUserId(tokenUser.getId());//操作用户
//            List<BillAddCollectionReq> list2 = new ArrayList<>();
//            list2.add(bacr);
//            Result result = financeBillService.addCollection(list2);
//            List<Long> lists = (List<Long>) result.getData();
//            if (lists != null && lists.size() > 0) {
//
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.failed(SystemError.IOTC_40008);
    }

    @Override
    public Result refund(OperatePromotionRefundReq req, TokenUser tokenUser) {
        try {
            QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(OperatePromotion::getId, req.getId())
                    .eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(OperatePromotion::getBusinessType, req.getBusinessType());
            OperatePromotion operatePromotion = baseMapper.selectOne(queryWrapper);
            //获取当前时间和星期数
            LocalDateTime now = LocalDateTime.now();

            //是否符合满减
            int i = req.getTotalPaidIn().compareTo(operatePromotion.getFullAmount());
            if (i < 0) {
                return Result.failed(SystemError.IOTC_400014);
            }
            //判断剩余金额是否足够
            int compare = operatePromotion.getStockAmount().compareTo(operatePromotion.getReductionAmount());
            if (compare < 0) {
                return Result.failed(SystemError.IOTC_400015);
            }
            //判断是否属于适用产品
            QueryWrapper<OperatePromotionProduct> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(OperatePromotionProduct::getCodeId, operatePromotion.getId())
                    .eq(OperatePromotionProduct::getRelationId, req.getRelationId())
                    .eq(OperatePromotionProduct::getIsDeleted, IsDeletedCode.NO.getCode());
            if (operatePromotionProductMapper.selectCount(wrapper) < 1) {
                return Result.failed(SystemError.IOTC_400016);
            }
            //判断是否符合优惠对象
            if (!getDiscountObjectsJsonBool(operatePromotion.getDiscountObjectsJson(), req.getDiscountObjectId())) {
                return Result.failed(SystemError.IOTC_400017);
            }
            //判断是否符合渠道范围
            if (!getDiscountObjectsJsonBool(operatePromotion.getChannelsJson(), req.getChannelId())) {
                return Result.failed(SystemError.IOTC_400018);
            }
            //判断是否符合适用部门
            if (!getDepartmentsJsonBool(operatePromotion.getDepartmentsJson(), tokenUser.getId())) {
                return Result.failed(SystemError.IOTC_400019);
            }
            //扣减剩余金额加上
            BigDecimal stockAmount = operatePromotion.getStockAmount().add(operatePromotion.getReductionAmount());
            //写入扣减名额和金额
            OperatePromotion promotion = new OperatePromotion();
            promotion.setId(req.getId());
            if (operatePromotion.getTotalDiscountQuota() != null) {
                //扣减名额加上
                promotion.setTotalDiscountQuota(operatePromotion.getTotalDiscountQuota() + 1);
            }
            promotion.setStockAmount(stockAmount);
            promotion.setGmtModified(now);
            promotion.setModifiedId(tokenUser.getId());
            int update = baseMapper.updateById(promotion);
            if (update > 0) {
                return Result.success();
            }
            //添加一条退款记录
//            BillAddRefundReq barr = EntityUtil.copy(req, BillAddRefundReq.class);
//            barr.setCollectionAmount(operatePromotion.getReductionAmount());//实际优惠金额
//            barr.setRefundTime(LocalDateTime.now());//退款时间当前
//            List<Long> list = new ArrayList<>();
//            list.add(req.getRelationId());
//            barr.setProductId(list);//产品ID
//            barr.setUserId(tokenUser.getId());//操作用户
//            List<BillAddRefundReq> list2 = new ArrayList<>();
//            list2.add(barr);
//            Result result = financeBillService.addRefund(list2);
//            List<Long> lists = (List<Long>) result.getData();
//            if (lists != null && lists.size() > 0) {
//
//            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.failed(SystemError.IOTC_40006);
    }

    @Override
    public List<Long> queryRelationIdList(Integer businessType) {
        QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OperatePromotion::getBusinessType, businessType)
                .eq(OperatePromotion::getStatus, OperatePromotionStatus.STATUS_4.getCode())
                .eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode())
                .orderByDesc(OperatePromotion::getGmtModified);
        List<OperatePromotion> operatePromotionList = baseMapper.selectList(queryWrapper);
        //获取当期时间
        LocalDateTime now = LocalDateTime.now();
        String week = String.valueOf(now.getDayOfWeek().getValue());
        List<Long> codeIdList = new ArrayList<>();
        for (OperatePromotion operatePromotion : operatePromotionList) {
            //判断条件(是否符合活动有效期)
            if (!(now.isAfter(operatePromotion.getActivityBegin()) && now.isBefore(operatePromotion.getActivityEnd()))) {
                operatePromotionList.remove(operatePromotion);
                continue;
            }
            //判断条件(是否符合活动周期)
            if (operatePromotion.getActivityCycle() != OperatePromotionActivityCycle.ACTIVITY_CYCLE_1.getCode()) {
                String[] strings = operatePromotion.getActivityCycleWeeks().split(",");
                List<String> list = Arrays.asList(strings);
                if (!list.contains(week)) {
                    operatePromotionList.remove(operatePromotion);
                    continue;
                }
            }
            //判斷條件(剩餘金額或剩餘名額不為0)
            if (operatePromotion.getStockNum() == 0 || operatePromotion.getStockAmount().equals(0)) {
                operatePromotionList.remove(operatePromotion);
                continue;
            }
            codeIdList.add(operatePromotion.getId());
        }
        if (CollectionUtils.isEmpty(codeIdList)) {
            return null;
        }
        QueryWrapper<OperatePromotionProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(OperatePromotionProduct::getCodeId, codeIdList);
        List<OperatePromotionProduct> operatePromotionProducts = operatePromotionProductMapper.selectList(wrapper);
//        List<OperatePromotionProduct> operatePromotionProducts = operatePromotionProductMapper.selectIds(codeIdList);
        List<Long> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(operatePromotionProducts)) {
            return null;
        }
        for (OperatePromotionProduct operatePromotionProduct : operatePromotionProducts) {
            list.add(operatePromotionProduct.getRelationId());
        }
        List<Long> myList = list.stream().distinct().collect(Collectors.toList());
        return myList;
    }

    @Override
    public Result approval(OperateBankApprovalReq req) {
        if (req.getApprovalId() == null) {
            return Result.failed(SystemError.SYS_402);
        }
        if (!ApprovalStatus.isCheckStatus(req.getApprovalStatus())) {
            return Result.failed(SystemError.SYS_402);
        }
        //审批前查询推广码信息
        QueryWrapper<OperatePromotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OperatePromotion::getId, req.getBusinessId())
                .eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO);
        OperatePromotion obp = baseMapper.selectOne(queryWrapper);
        if (obp == null) {
            return Result.failed(SystemError.SYS_411);
        }
        //审批
        Result<ApprovalCheckDTO> result = sysApprovalService.check(req.getApprovalId(), req.getUserId(),
                req.getApprovalStatus(), req.getRemark());
        if (!result.isSuccess()) {
            SystemError systemError = SystemError.getDefined(result.getCode());
            return Result.failed(systemError);
        }
        if (result.getData() == null || !result.getData().getIsFinish()) {
            return Result.success();
        }
        //审批状态（0：撤回，4：审批不通过，3：审批通过）
        if (req.getApprovalStatus() == SupplierAddCheckStatus.REVIEW_YES.getCode()) {
            //审批通过
            obp.setStatus(OperatePromotionStatus.STATUS_4.getCode());
        } else if (req.getApprovalStatus() == SupplierAddCheckStatus.REVIEW_NO.getCode()) {
            //审批不通过
            obp.setStatus(OperatePromotionStatus.STATUS_3.getCode());
        } else {
            //撤回
            obp.setStatus(OperatePromotionStatus.STATUS_1.getCode());
        }
        LocalDateTime nowLocalDateTime = LocalDateTime.now();
        obp.setModifiedId(req.getUserId());
        obp.setGmtModified(nowLocalDateTime);
        baseMapper.updateById(obp);
        return Result.success();
    }

    @Override
    public void reflush() {
        QueryWrapper<OperatePromotion> qwop = new QueryWrapper<>();
        qwop.lambda().eq(OperatePromotion::getIsDeleted, IsDeletedCode.NO.getCode())
                .le(OperatePromotion::getActivityEnd, LocalDateTime.now())
                .eq(OperatePromotion::getStatus, OperatePromotionStatus.STATUS_4.getCode());
        List<OperatePromotion> operatePromotions = baseMapper.selectList(qwop);
        //查到过期的推广码就修改为失效
        if (operatePromotions != null && operatePromotions.size() > 0) {
            operatePromotions.stream().forEach(e -> {
                e.setStatus(OperatePromotionStatus.STATUS_6.getCode());
                baseMapper.updateById(e);
            });
        }
    }

    private boolean getDepartmentsJsonBool(List<OperateJson> djs, Long userId) {
        if (djs == null || djs.size() == 0) {
            return true;//不选部门所有都可以用直接跳过
        }
        String s = JSON.toJSONString(djs);
        JSONArray objects = JSONArray.parseArray(s);
        List<OperateJson> list = objects.toJavaList(OperateJson.class);
        //判断是否符合适用部门
        if (list != null && list.size() > 0) {
            for (OperateJson department : list) {
                if (sysDepartmentService.isExist(department.getId(), userId)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean getChannelsJsonBool(List<OperateJson> cjs, Long channelId) {
        if (cjs == null || cjs.size() == 0) {
            //不限制渠道范围
            return true;
        }
        String s = JSON.toJSONString(cjs);
        JSONArray objects = JSONArray.parseArray(s);
        List<OperateJson> list = objects.toJavaList(OperateJson.class);
        //判断是否符合渠道范围
        if (list != null && list.size() > 0) {
            List<Long> collect = list.stream().map(e -> e.getId()).collect(Collectors.toList());
            //如果配置了渠道范围，切又不在配置的渠道范围内就错误
            if (!collect.contains(channelId)) {
                return false;
            }
            return true;
        } else {
            return false;
        }
    }

    private boolean getDiscountObjectsJsonBool(List<OperateJson> ojs, Long discountObjectId) {
        if (ojs == null || ojs.size() == 0) {
            //不限制优惠对象
            return true;
        }
        String s = JSON.toJSONString(ojs);
        JSONArray objects = JSONArray.parseArray(s);
        List<OperateJson> list = objects.toJavaList(OperateJson.class);
        //判断是否符合优惠对象
        if (list != null && list.size() > 0) {
            List<Long> collect = list.stream().map(e -> e.getId()).collect(Collectors.toList());
            //如果配置了优惠对象，切又不在配置的范围内就错误
            if (collect.contains(discountObjectId)) {
                return true;
            }
        }
        return false;
    }
}
